package com.common.retrofit;

import android.content.Context;
import android.os.Build;
import android.text.TextUtils;

import com.common.config.Global;
import com.lsz.atm.json.LoginEntity;
import com.util_code.BuildConfig;
import com.util_code.dagger.qualifier.ApplicationContext;
import com.util_code.dagger.qualifier.OkhttpCache;
import com.util_code.okhttp.OkhttpCacheUtils;
import com.util_code.okhttp.RequestMethod;
import com.util_code.oklog.OkLogInterceptor;
import com.util_code.utils.AndroidUtils;
import com.util_code.utils.NetUtils;
import com.common.config.Api;
import com.common.dagger.scope.MyAppScope;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.franmontiel.persistentcookiejar.ClearableCookieJar;
import com.franmontiel.persistentcookiejar.PersistentCookieJar;
import com.franmontiel.persistentcookiejar.cache.SetCookieCache;
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.inject.Inject;

import okhttp3.Cookie;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;

@MyAppScope
public class MyOkhttpHelper {

    private static ClearableCookieJar sCookieJar;
    private OkHttpClient mHttpClient = null;

    @Inject
    public MyOkhttpHelper(@ApplicationContext Context context, @OkhttpCache File cacheFile) {

        sCookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(AndroidUtils.getContext()));
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.cache(OkhttpCacheUtils.createCache(context, cacheFile.getAbsolutePath()))
                .cookieJar(sCookieJar)
                .addInterceptor(userAgentInterceptor)
                .addInterceptor(headerInterceptor);

        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(loggingInterceptor);
            builder.addNetworkInterceptor(new StethoInterceptor());
        }

        OkLogInterceptor okLogInterceptor = new OkLogInterceptor();
        builder.addInterceptor(okLogInterceptor);

        mHttpClient = builder.build();
    }

    private static Interceptor userAgentInterceptor = new Interceptor() {
        private static final String USER_AGENT_HEADER_NAME = "User-Agent";

        @Override
        public Response intercept(Chain chain) throws IOException {
            final Request originalRequest = chain.request();
            final Request requestWithUserAgent = originalRequest.newBuilder()
                    .removeHeader(USER_AGENT_HEADER_NAME)
                    .addHeader(USER_AGENT_HEADER_NAME, formatUserAgent())
                    .build();
            return chain.proceed(requestWithUserAgent);
        }
    };

    private static String formatUserAgent() {
        StringBuilder result = new StringBuilder();
        result.append("Android");
        result.append(";");
        result.append(Build.VERSION.RELEASE);
        result.append(";");
        result.append(Build.VERSION.SDK_INT);
        result.append(";");
        result.append(BuildConfig.VERSION_NAME);
        result.append(";");
        result.append(BuildConfig.VERSION_CODE);
        result.append(";");
        result.append(NetUtils.getNetworkType().name());
        result.append(";");
        result.append(Build.MODEL);
        result.append(";");
        return result.toString().replaceAll("\\s*", "");
    }

    private static Interceptor headerInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();

            Request.Builder newRequestBuilder = originalRequest.newBuilder();
            newRequestBuilder.addHeader("Accept-Resthub-Spec", "application/vnd.resthub.v2+json");
            newRequestBuilder.addHeader("Uni-Source", "Android (OS/" + Build.VERSION.SDK_INT + "APP/" + BuildConfig.VERSION_NAME + ")");

            LoginEntity loginBean = Global.getLoginBean();
            if (loginBean != null && loginBean.accessToken != null && !TextUtils.isEmpty(loginBean.accessToken.access_token)) {
                LoginEntity.AccessTokenBean accessToken = loginBean.accessToken;
                newRequestBuilder.addHeader("Authorization", accessToken.token_type + " " + accessToken.access_token);
            }
            HttpUrl.Builder builderUrl = originalRequest.url()
                    .newBuilder()
                    .addQueryParameter("_platform", "app")
                    .addQueryParameter("_os", "android")
                    .addQueryParameter("_sysVersion", "" + Build.VERSION.SDK_INT)
                    .addQueryParameter("_appVersion", "" + BuildConfig.VERSION_NAME)
                    .addQueryParameter("_model", "" + "" + Build.MODEL)
                    .addQueryParameter("_caller", "liang_atm")
                    .addQueryParameter("_appChannel", "")
                    .addQueryParameter("channel", "02") /*old version channel*/
                    .addQueryParameter("_openUDID", AndroidUtils.getDeviceId());

            String requestUrl = builderUrl.build().toString();
            StringBuilder queryString = new StringBuilder(requestUrl.substring(requestUrl.indexOf("?") + 1));

            StringBuilder postString = new StringBuilder();
            if (RequestMethod.supportBody(originalRequest.method())) {
                if (originalRequest.body() instanceof FormBody) {
                    FormBody.Builder formbuilder = new FormBody.Builder();
                    FormBody formBody = (FormBody) originalRequest.body();
                    for (int i = 0; i < formBody.size(); i++) {
                        formbuilder.add(formBody.name(i), formBody.value(i));
                    }
                    formbuilder.add("channel", "02");
                    formBody = (FormBody) formbuilder.build();
                    for (int i = 0; i < formBody.size(); i++) {
                        postString.append(postString.length() > 0 ? "&" : "")
                                .append(formBody.encodedName(i))
                                .append("=")
                                .append(formBody.encodedValue(i) == null ? "" : formBody.encodedValue(i));
                    }
                    newRequestBuilder.method(originalRequest.method(), formbuilder.build());
                }
            }

            Request newRequest = newRequestBuilder.url(builderUrl.build()).build();
            Response response = chain.proceed(newRequestBuilder.build());
            String responseEncrypt = TextUtils.isEmpty(response.header("Content-Encrypt")) ? response
                    .header("Content_Encrypt") : response.header("Content-Encrypt");// Content-Encrypt="AES/QBSH"
            if (!TextUtils.isEmpty(responseEncrypt)) {
                MediaType mediaType = response.body().contentType();
                try {
                    String responseContent = response.body().string();
                    return response.newBuilder()
                            .body(ResponseBody.create(mediaType, responseContent))
                            .build();
                } catch (Exception e) {
                    return response.newBuilder()
                            .body(ResponseBody.create(mediaType, ""))
                            .build();
                }
            }
            return response;
        }
    };


    public static List<Cookie> getHttpCookieList() {
        return sCookieJar.loadForRequest(HttpUrl.parse(Api.BASE_URL));
    }

    public static String getHttpCookieString() {
        StringBuilder stringBuilder = new StringBuilder();
        List<Cookie> cookieList = getHttpCookieList();
        for (Cookie cookie : cookieList) {
            stringBuilder.append(cookie.toString()).append(";");
        }
        if (stringBuilder.length() > 0) {
            int last = stringBuilder.lastIndexOf(";");
            if (stringBuilder.length() - 1 == last) {
                stringBuilder.deleteCharAt(last);
            }
        }

        return stringBuilder.toString();
    }

    public static void clearCookie() {
        sCookieJar.clear();
    }

    public OkHttpClient getHttpClient() {
        return mHttpClient;
    }

}
